﻿using System.Diagnostics;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace Sgr.DataCategories.Stores
{
    /// <summary>
    /// 默认本地行政区划存储实现
    /// </summary>
    public class DefaultLocalAdmDivStore : IAdmDivStore
    {
        private const int DefaultCacheExpirationSeconds = 7200; // 2小时
        private const int DefaultBackgroundRefreshTimeoutSeconds = 60;

        private readonly GenericLocalCache<IReadOnlyList<AdmDiv>> _cache;

        public DefaultLocalAdmDivStore(IConfiguration configuration, ILogger<DefaultLocalAdmDivStore> logger)
        {
            Check.NotNull(configuration, nameof(configuration));

            _cache = new GenericLocalCache<IReadOnlyList<AdmDiv>>(
                "AdmDiv",
                configuration.GetValue("Sgr:Caching:AdmDivExpiration", DefaultCacheExpirationSeconds),
                configuration.GetValue("Sgr:Caching:AdmDivBackgroundRefreshTimeout", DefaultBackgroundRefreshTimeoutSeconds),
                logger);
        }

        public async Task<IEnumerable<AdmDiv>> GetOrAddAsync(
            Func<CancellationToken, Task<IEnumerable<AdmDiv>>> valueFactory,
            CancellationToken cancellationToken = default)
        {
            return await _cache.GetOrAddAsync(
                  async ct =>
                  {
                      var items = await valueFactory(ct).ConfigureAwait(false);
                      return (items ?? Enumerable.Empty<AdmDiv>()).ToList().AsReadOnly();
                  },
                  cancellationToken
              ).ConfigureAwait(false);
        }

        public async Task RefreshAsync(
            IEnumerable<AdmDiv> items,
            CancellationToken cancellationToken = default)
        {
            var list = (items ?? Enumerable.Empty<AdmDiv>()).ToList().AsReadOnly();
            await _cache.RefreshAsync(list, cancellationToken).ConfigureAwait(false);
        }

        public async Task ClearAsync(CancellationToken cancellationToken = default)
        {
            await _cache.ClearAsync(cancellationToken).ConfigureAwait(false);
        }

        public void Dispose()
        {
            _cache.Dispose();
        }
    }
}